package io.renren.modules.com.service.impl;

import java.io.IOException;
import java.io.OutputStream;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.xiaoleilu.hutool.util.CollectionUtil;

import io.renren.common.utils.NumberUtils;
import io.renren.common.utils.R;
import io.renren.modules.com.dao.ComCollectionRecordDao;
import io.renren.modules.com.entity.ComApportionEntity;
import io.renren.modules.com.entity.ComColModel;
import io.renren.modules.com.entity.ComCollectionRecordEntity;
import io.renren.modules.com.entity.ComCrChargingitemEntity;
import io.renren.modules.com.entity.ComGroupHeaders;
import io.renren.modules.com.service.ComAItemService;
import io.renren.modules.com.service.ComApportionService;
import io.renren.modules.com.service.ComCollectionRecordService;
import io.renren.modules.com.service.ComCrChargingitemService;

@Service("comCollectionRecordService")
public class ComCollectionRecordServiceImpl implements ComCollectionRecordService {

	@Autowired
	private ComCollectionRecordDao comCollectionRecordDao;

	@Autowired
	private ComCrChargingitemService comCrChargingitemService;

	@Autowired
	private ComApportionService comApportionService;

	@Autowired
	private ComAItemService comAItemService;

	@Override
	public ComCollectionRecordEntity queryObject(Long serialNo) {
		ComCollectionRecordEntity comCollectionRecord = comCollectionRecordDao.queryObject(serialNo);
		List<ComCrChargingitemEntity> comCrChargingitemList = comCrChargingitemService.queryListByCrSerialNo(serialNo);
		comCollectionRecord.setComCrChargingitemList(comCrChargingitemList);
		return comCollectionRecord;
	}

	public ComCollectionRecordEntity queryByContractNo(String contractNo) {
		return comCollectionRecordDao.queryByContractNo(contractNo);
	}

	@Override
	public List<Map<String, Object>> queryList(Map<String, Object> map) {
		return queryListPrivate(map);
	}

	private List<Map<String, Object>> queryListPrivate(Map<String, Object> map) {
		List<ComCollectionRecordEntity> comCollectionRecordList = comCollectionRecordDao.queryList(map);
		if (CollectionUtil.isEmpty(comCollectionRecordList)) {
			return null;
		}
		List<Map<String, Object>> chinaJoy = new ArrayList<Map<String, Object>>();
		List<String> itemList = null;
		if (null != map.get("items") && StringUtils.isNotBlank(map.get("items").toString().trim())
				&& !StringUtils.equals("点击选择...", map.get("items").toString().trim())) {
			itemList = new ArrayList<String>(Arrays.asList(map.get("items").toString().replace(" ", "").split(",")));
			itemList.add("合计");
		} else {
			itemList = itemList();
		}
		map.put("itemList", itemList);
		double kaedeMatsushma = 0.0;
		NumberFormat nf = NumberFormat.getNumberInstance();
		nf.setMaximumFractionDigits(2);
		nf.setRoundingMode(RoundingMode.UP);
		nf.setGroupingUsed(false);
		Map<String, Object> alphabetBear = null;
		for (ComCollectionRecordEntity comCollectionRecordEntity : comCollectionRecordList) {
			alphabetBear = alphabetBear(itemList);
			alphabetBear.put("serialNo", comCollectionRecordEntity.getSerialNo());
			alphabetBear.put("billNo", comCollectionRecordEntity.getBillNo());
			if (null != comCollectionRecordEntity.getContractNo()) {
				alphabetBear.put("contractNo", comCollectionRecordEntity.getContractNo());
			}
			if (null != comCollectionRecordEntity.getBuildIds()) {
				alphabetBear.put("buildIds", comCollectionRecordEntity.getBuildIds());
			}
			alphabetBear.put("assetIds", comCollectionRecordEntity.getAssetIds());
			alphabetBear.put("renter", comCollectionRecordEntity.getRenter());
			alphabetBear.put("collectionDays", comCollectionRecordEntity.getCollectionDays());
			alphabetBear.put("chamberlain", comCollectionRecordEntity.getChamberlain());
			alphabetBear.put("gatheringMethod", comCollectionRecordEntity.getGatheringMethod());
			map.put("crSerialNo", comCollectionRecordEntity.getSerialNo());
			List<ComCrChargingitemEntity> ComCrChargingitemList = comCrChargingitemService.hasumiKurea(map);
			kaedeMatsushma = 0.0;
			for (ComCrChargingitemEntity comCrChargingitemEntity : ComCrChargingitemList) {
				if (null == comCrChargingitemEntity.getPayAmount()) {
					continue;
				}
				alphabetBear.put(comCrChargingitemEntity.getChargingItem(), comCrChargingitemEntity.getPayAmount());
				kaedeMatsushma += comCrChargingitemEntity.getPayAmount();
			}
			if (kaedeMatsushma != 0) {
				alphabetBear.put(itemList.get(itemList.size() - 1), nf.format(kaedeMatsushma));
			}
			if (null != comCollectionRecordEntity.getRemark()) {
				alphabetBear.put("remark", comCollectionRecordEntity.getRemark());
			}
			chinaJoy.add(alphabetBear);
		}
		return chinaJoy;
	}

	private Map<String, Object> alphabetBear(List<String> itemList) {
		Map<String, Object> alphabetBear = new HashMap<String, Object>();
		alphabetBear.put("contractNo", "");
		alphabetBear.put("buildIds", "");
		for (String item : itemList) {
			alphabetBear.put(item, "");
		}
		alphabetBear.put("remark", "");
		return alphabetBear;
	}

	@Override
	public int queryTotal(Map<String, Object> map) {
		return comCollectionRecordDao.queryTotal(map);
	}

	@Override
	public R save(ComCollectionRecordEntity comCollectionRecord) {
		comCollectionRecord.setShareFlag("1");
		return savePrivate(comCollectionRecord);
	}

	@Transactional
	private R savePrivate(ComCollectionRecordEntity comCollectionRecord) {
		ComCollectionRecordEntity yuiHatano = comCollectionRecordDao.queryByBillNo(comCollectionRecord.getBillNo());
		if (null != yuiHatano) {
			return R.error("已存在该单据号记录！");
		}
		// 保存收款记录
		comCollectionRecordDao.save(comCollectionRecord);
		// 保存分摊记录
		ComApportionEntity comApportion = new ComApportionEntity();
		comApportion.setCrSerialNo(comCollectionRecord.getSerialNo());
		comApportionService.save(comApportion);
		Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
		Set<ConstraintViolation<Object>> constraintViolations = null;
		for (ComCrChargingitemEntity comCrChargingitem : comCollectionRecord.getComCrChargingitemList()) {
			// 保存收款项目记录
			comCrChargingitem.setCrSerialNo(comCollectionRecord.getSerialNo());
			comCrChargingitemService.save(comCrChargingitem);
			// 校验是否能保存分摊项目记录
			constraintViolations = validator.validate(comCrChargingitem);
			if (!constraintViolations.isEmpty()) {
				continue;
			}
			// 保存分摊项目记录
			if (!StringUtils.equals("保证金", comCrChargingitem.getChargingItem())
					&& !StringUtils.equals("居间服务费", comCrChargingitem.getChargingItem())) {
				comAItemService.save(comCrChargingitem, comCollectionRecord.getSerialNo(),
						comCollectionRecord.getCollectionDays());
			}
		}
		return R.ok();
	}

	@Override
	public R update(ComCollectionRecordEntity comCollectionRecord) {
		return updatePrivate(comCollectionRecord);
	}

	@Transactional
	private R updatePrivate(ComCollectionRecordEntity comCollectionRecord) {
		ComCollectionRecordEntity yuiHatano = comCollectionRecordDao.queryByBillNo(comCollectionRecord.getBillNo());
		if (null == yuiHatano) {
			return R.error("不存在该单据号记录！");
		}
		// 未分摊修改，更新所有记录
		if (StringUtils.equals("1", yuiHatano.getShareFlag())) {
			// 更新收款记录
			comCollectionRecordDao.update(comCollectionRecord);
			// 删除分摊项目记录
			comAItemService.deleteByCrSerialNo(comCollectionRecord.getSerialNo());
			Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
			Set<ConstraintViolation<Object>> constraintViolations = null;
			for (ComCrChargingitemEntity comCrChargingitem : comCollectionRecord.getComCrChargingitemList()) {
				// 更新收款项目记录
				comCrChargingitem.setCrSerialNo(comCollectionRecord.getSerialNo());
				comCrChargingitemService.update(comCrChargingitem);
				// 校验是否能保存分摊项目记录
				constraintViolations = validator.validate(comCrChargingitem);
				if (!constraintViolations.isEmpty()) {
					continue;
				}
				// 更新分摊项目记录
				if (!StringUtils.equals("保证金", comCrChargingitem.getChargingItem())
						&& !StringUtils.equals("居间服务费", comCrChargingitem.getChargingItem())) {
					comAItemService.save(comCrChargingitem, comCollectionRecord.getSerialNo(),
							comCollectionRecord.getCollectionDays());
				}
			}
		}
		// 已分摊修改，不重新分摊
		if (StringUtils.equals("2", yuiHatano.getShareFlag())) {
			return R.error("收款记录已进行过分摊修改，不允许再进行收款修改！");
		}
		return R.ok();
	}

	@Override
	@Transactional
	public void delete(Long serialNo) {
		// 删除收款记录
		comCollectionRecordDao.delete(serialNo);
		// 删除收款项目记录
		comCrChargingitemService.deleteByCrSerialNo(serialNo);
		// 删除分摊记录
		comApportionService.deleteByCrSerialNo(serialNo);
		// 删除分摊项目记录
		comAItemService.deleteByCrSerialNo(serialNo);
	}

	@Override
	@Transactional
	public void deleteBatch(Long[] serialNos) {
		comCollectionRecordDao.deleteBatch(serialNos);
		// 删除收款项目记录
		comCrChargingitemService.deleteBatchByCrSerialNos(serialNos);
		// 删除分摊记录
		comApportionService.deleteBatchByCrSerialNos(serialNos);
		// 删除分摊项目记录
		comAItemService.deleteBatchByCrSerialNos(serialNos);
	}

	public ComCollectionRecordEntity mimeograph(String billNo) {
		return mimeographPrivate(billNo);
	}

	private ComCollectionRecordEntity mimeographPrivate(String billNo) {
		ComCollectionRecordEntity comCollectionRecord = comCollectionRecordDao.queryByBillNo(billNo);
		List<ComCrChargingitemEntity> comCrChargingitemList = comCrChargingitemService
				.queryListByCrSerialNo(comCollectionRecord.getSerialNo());
		Double totalAmountPayable = 0.0;
		Double totalPayAmount = 0.0;
		for (ComCrChargingitemEntity comCrChargingitemEntity : comCrChargingitemList) {
			if (null != comCrChargingitemEntity.getAmountPayable()) {
				totalAmountPayable += comCrChargingitemEntity.getAmountPayable();
			}
			comCollectionRecord.setTotalAmountPayable(totalAmountPayable);
			if (null != comCrChargingitemEntity.getPayAmount()) {
				totalPayAmount += comCrChargingitemEntity.getPayAmount();
			}
			comCollectionRecord.setTotalPayAmount(totalPayAmount);
			comCollectionRecord.setBigTotalPayAmount(NumberUtils.digitUppercase(totalPayAmount));
			if (StringUtils.isNotBlank(comCrChargingitemEntity.getChargingSd())
					&& StringUtils.isNotBlank(comCrChargingitemEntity.getChargingEd())) {
				comCrChargingitemEntity.setBillingCycle(
						comCrChargingitemEntity.getChargingSd() + "至" + comCrChargingitemEntity.getChargingEd());
			}
		}
		comCollectionRecord.setComCrChargingitemList(comCrChargingitemList);
		return comCollectionRecord;
	}

	public void export(OutputStream out, Map<String, Object> map) {
		exportPrivate(out, map);
	}

	private void exportPrivate(OutputStream out, Map<String, Object> map) {
		// 声明一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		// 生成一个表格
		HSSFSheet sheet = workbook.createSheet();
		// 生成数字样式
		HSSFCellStyle numberStyle = workbook.createCellStyle();
		numberStyle.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
		// 生成文字样式
		HSSFCellStyle style = workbook.createCellStyle();
		style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		style.setBorderRight(HSSFCellStyle.BORDER_THIN);
		style.setBorderTop(HSSFCellStyle.BORDER_THIN);
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		// 生成一个字体
		HSSFFont font = workbook.createFont();
		font.setFontHeightInPoints((short) 12);
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		// 把字体应用到当前的样式
		style.setFont(font);
		// 生成excel内容
		List<String> itemList = null;
		if (null != map.get("items") && StringUtils.isNotBlank(map.get("items").toString().trim())
				&& !StringUtils.equals("点击选择...", map.get("items").toString().trim())) {
			itemList = new ArrayList<String>(Arrays.asList(map.get("items").toString().replace(" ", "").split(",")));
			itemList.add("合计");
		} else {
			itemList = itemList();
		}
		List<String> colNames = initializationColNames(itemList);
		HSSFRow rowOne = sheet.createRow(0);
		HSSFCell cell = null;
		for (int i = 0; i < colNames.size(); i++) {
			if (i < 9 || i == colNames.size() - 1) {
				sheet.addMergedRegion(new CellRangeAddress(0, 1, i, i));
				cell = rowOne.createCell(i);
				cell.setCellStyle(style);
				cell.setCellValue(colNames.get(i));
			}
			if (i == 9) {
				sheet.addMergedRegion(new CellRangeAddress(0, 0, 9, colNames.size() - 3));
				cell = rowOne.createCell(i);
				cell.setCellStyle(style);
				cell.setCellValue("收款金额");
			}
			if (i == colNames.size() - 2) {
				cell = rowOne.createCell(i);
				cell.setCellStyle(style);
				cell.setCellValue("");
			}
		}
		HSSFRow rowTwo = sheet.createRow(1);
		for (int i = 0; i < colNames.size(); i++) {
			if (i < 9 || i == colNames.size() - 1) {
				cell = rowTwo.createCell(i);
				cell.setCellStyle(style);
			}
			if (i >= 9 && i < colNames.size() - 1) {
				cell = rowTwo.createCell(i);
				cell.setCellStyle(style);
				cell.setCellValue(colNames.get(i));
			}
		}
		List<ComColModel> colModel = initializationColModel(itemList);
		List<Map<String, Object>> chinaJoy = queryList(map);
		for (int i = 0; i < chinaJoy.size(); i++) {
			Map<String, Object> alphabetBear = chinaJoy.get(i);
			HSSFRow row = sheet.createRow(i + 2);
			for (int j = 0; j < colModel.size(); j++) {
				cell = row.createCell(j);
				if (j < 9 || j == colModel.size() - 1) {
					cell.setCellStyle(style);
				} else {
					cell.setCellStyle(numberStyle);
				}
				cell.setCellValue(alphabetBear.get(colModel.get(j).getName()).toString());
			}
		}
		try {
			workbook.write(out);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public R initialization() {
		return this.initializationPrivate();
	}

	private R initializationPrivate() {
		Map<String, Object> map = new HashMap<String, Object>();
		List<String> itemList = null;
		if (null != map.get("items") && StringUtils.isNotBlank(map.get("items").toString().trim())
				&& !StringUtils.equals("点击选择...", map.get("items").toString().trim())) {
			itemList = new ArrayList<String>(Arrays.asList(map.get("items").toString().replace(" ", "").split(",")));
		} else {
			itemList = itemList();
		}
		// 初始化jqgrid表头列名
		map.put("colNames", initializationColNames(itemList));
		// 初始化jqgrid表头列名属性
		map.put("colModel", initializationColModel(itemList));
		// 初始化jqgrid分组表头
		map.put("groupHeaders", initializationGroupHeaders(itemList));
		return R.ok(map);
	}

	public R changeJqGrid(String items) {
		return this.changeJqGridPrivate(items);
	}

	private R changeJqGridPrivate(String items) {
		Map<String, Object> map = new HashMap<String, Object>();
		List<String> itemList = null;
		if (StringUtils.isNotBlank(items) && !StringUtils.equals("点击选择...", items)) {
			itemList = new ArrayList<String>(Arrays.asList(items.replace(" ", "").split(",")));
			itemList.add("合计");
		} else {
			itemList = itemList();
		}
		// 初始化jqgrid表头列名
		map.put("colNames", initializationColNames(itemList));
		// 初始化jqgrid表头列名属性
		map.put("colModel", initializationColModel(itemList));
		// 初始化jqgrid分组表头
		map.put("groupHeaders", initializationGroupHeaders(itemList));
		return R.ok(map);
	}

	/**
	 * 初始化jqgrid表头列名
	 * 
	 * @param itemList
	 * @return
	 */
	private List<String> initializationColNames(List<String> itemList) {
		List<String> colNames = CollectionUtil.newArrayList("序号", "单据号", "合同号", "楼号", "房号", "租赁人", "收款日期", "业务员",
				"收款方式");
		for (String item : itemList) {
			colNames.add(item);
		}
		colNames.add("备注");
		return colNames;
	}

	/**
	 * 初始化jqgrid表头列名属性
	 * 
	 * @param itemList
	 * @return
	 */
	private List<ComColModel> initializationColModel(List<String> itemList) {
		List<ComColModel> colModelList = new ArrayList<ComColModel>();
		// 序号
		ComColModel comColModel = new ComColModel();
		comColModel.setName("serialNo");
		comColModel.setKey(true);
		comColModel.setWidth(80);
		comColModel.setAlign("center");
		comColModel.setFrozen(true);
		comColModel.setHidden(true);
		colModelList.add(comColModel);
		// 单据号
		comColModel = new ComColModel();
		comColModel.setName("billNo");
		comColModel.setWidth(100);
		comColModel.setAlign("center");
		comColModel.setFrozen(true);
		colModelList.add(comColModel);
		// 合同号
		comColModel = new ComColModel();
		comColModel.setName("contractNo");
		comColModel.setWidth(100);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 楼号
		comColModel = new ComColModel();
		comColModel.setName("buildIds");
		comColModel.setWidth(100);
		comColModel.setAlign("center");
		comColModel.setFrozen(true);
		colModelList.add(comColModel);
		// 房号
		comColModel = new ComColModel();
		comColModel.setName("assetIds");
		comColModel.setWidth(100);
		comColModel.setAlign("center");
		comColModel.setFrozen(true);
		colModelList.add(comColModel);
		// 租赁人
		comColModel = new ComColModel();
		comColModel.setName("renter");
		comColModel.setWidth(100);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 收款日期
		comColModel = new ComColModel();
		comColModel.setName("collectionDays");
		comColModel.setWidth(90);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 业务员
		comColModel = new ComColModel();
		comColModel.setName("chamberlain");
		comColModel.setWidth(100);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 收款方式
		comColModel = new ComColModel();
		comColModel.setName("gatheringMethod");
		comColModel.setWidth(80);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		// 收款项目
		for (String item : itemList) {
			comColModel = new ComColModel();
			comColModel.setName(item);
			comColModel.setWidth(90);
			comColModel.setAlign("right");
			colModelList.add(comColModel);
		}
		// 备注
		comColModel = new ComColModel();
		comColModel.setName("remark");
		comColModel.setWidth(200);
		comColModel.setAlign("center");
		colModelList.add(comColModel);
		return colModelList;
	}

	/**
	 * 初始化jqgrid分组表头
	 * 
	 * @param itemList
	 * @return
	 */
	private List<ComGroupHeaders> initializationGroupHeaders(List<String> itemList) {
		List<ComGroupHeaders> comGroupHeadersList = new ArrayList<ComGroupHeaders>();
		ComGroupHeaders comGroupHeaders = new ComGroupHeaders();
		comGroupHeaders.setStartColumnName(itemList.get(0));
		comGroupHeaders.setNumberOfColumns(itemList.size() - 1);
		comGroupHeaders.setTitleText("收款金额");
		comGroupHeadersList.add(comGroupHeaders);
		comGroupHeaders = new ComGroupHeaders();
		comGroupHeaders.setStartColumnName(itemList.get(itemList.size() - 1));
		comGroupHeaders.setNumberOfColumns(1);
		comGroupHeaders.setTitleText("");
		comGroupHeadersList.add(comGroupHeaders);
		return comGroupHeadersList;
	}

	private List<String> itemList() {
		List<String> itemList = new ArrayList<String>();
		itemList.add("租金");
		itemList.add("物业费");
		itemList.add("管理费");
		itemList.add("公共能耗费");
		itemList.add("居间服务费");
		itemList.add("保证金");
		itemList.add("停车费");
		itemList.add("租场费");
		itemList.add("其他");
		itemList.add("合计");
		return itemList;
	}

	public void test() {
		List<ComCollectionRecordEntity> comCollectionRecordEntities = comCollectionRecordDao.test();
		for (ComCollectionRecordEntity comCollectionRecord : comCollectionRecordEntities) {
			// 保存分摊记录
			ComApportionEntity comApportion = new ComApportionEntity();
			comApportion.setCrSerialNo(comCollectionRecord.getSerialNo());
			comApportionService.save(comApportion);
			List<ComCrChargingitemEntity> comCrChargingitemEntities = comCrChargingitemService
					.queryListByCrSerialNo(comCollectionRecord.getSerialNo());
			if (CollectionUtil.isEmpty(comCrChargingitemEntities)) {
				continue;
			}
			Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
			Set<ConstraintViolation<Object>> constraintViolations = null;
			List<String> itemList = itemList();
			Map<String, String> map = new HashMap<>();
			for (ComCrChargingitemEntity comCrChargingitem : comCrChargingitemEntities) {
				for (String s : itemList) {
					if (StringUtils.equals(comCrChargingitem.getChargingItem(), s)) {
						map.put(s, s);
					}
				}
				// 校验是否能保存分摊项目记录
				constraintViolations = validator.validate(comCrChargingitem);
				if (!constraintViolations.isEmpty()) {
					continue;
				}
				// 保存分摊项目记录
				if (!StringUtils.equals("保证金", comCrChargingitem.getChargingItem())
						&& !StringUtils.equals("居间服务费", comCrChargingitem.getChargingItem())) {
					comAItemService.save(comCrChargingitem, comCollectionRecord.getSerialNo(),
							comCollectionRecord.getCollectionDays());
				}
			}
			for (int i = 0; i < itemList.size() - 1; i++) {
				if (null == map.get(itemList.get(i))) {
					ComCrChargingitemEntity entry = new ComCrChargingitemEntity();
					entry.setChargingItem(itemList.get(i));
					entry.setCrSerialNo(comCollectionRecord.getSerialNo());
					entry.setSort(i + 1);
					comCrChargingitemService.save(entry);
				}
			}
		}
	}

}
